package com.chinatechstar.component.commons.utils;

import java.io.*;
import java.util.List;

/**
 * 克隆对象工具栏
 *
 * @author Rei
 */
public class CloneUtils {

    /**
     * 对象需要实现Serializable接口
     * 对象内部的属性均可序列化
     * 注意方法和属性的特殊修饰符。比如final、static变量的序列化问题会被引入到对象拷贝中。transient变量不会序列化。
     *
     * @param obj 对象
     * @param <T> 泛型
     * @return 泛型对象
     */
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T clone(T obj) {
        T cloneObj = null;
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;

        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(obj);

            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ois = new ObjectInputStream(bais);
            cloneObj = (T) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeObjectStream(oos, ois);
        }
        return cloneObj;
    }

    /**
     * 序列化方法克隆List
     *
     * @param src 源数据
     * @param <T> 泛型
     * @return List<T>
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> clone(List<T> src) {
        List<T> dest = null;
        ObjectOutputStream oos = null;
        ObjectInputStream ois = null;

        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(src);

            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ois = new ObjectInputStream(bais);

            dest = (List<T>) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeObjectStream(oos, ois);
        }

        return dest;
    }

    /**
     * 关闭流
     *
     * @param oos ObjectOutputStream
     * @param ois ObjectInputStream
     */
    private static void closeObjectStream(ObjectOutputStream oos, ObjectInputStream ois) {
        if (oos != null) {
            try {
                oos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (ois != null) {
            try {
                ois.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
